#include "ArmyState.h"
#include "UserAPI.h"
#include "BasicAI.h"
#include "params.h"

using namespace ArmyStateNS;

void FastOccupyingState::execute()
{
	BasicAI *ai = BasicAI::instance();
	UserAPI &api = ai->get_api();

	if (m_target == Position(-1, -1))
	{
		Position target;
		bool found = OccupyingState::find_target(m_name, target);
		if (found)
		{
			m_target = target;
			OccupyingState::assign(m_name, m_target);
		} else
		{
			enter_state(m_name, this, new WithdrawState(m_name));
			return;
		}
	}

	LandCity* city = api.GetCity(m_target);
	LOG_ASSERT(city, "city is NULL, no city lies at m_target");
	if (city->owner != -1)
	{
		if (city->owner == api.get_my_id())
		{
			LOG << get_type() << " occupied already" << endl;
			enter_state(m_name, this, new ManageState(m_name, m_target));
			return;
		}
		else
		{
			LOG << get_type() << " occupied by enemy" << endl;
			enter_state(m_name, this, new WithdrawState(m_name));
			return;
		}
		return;
	}

	Position start = api.GetCntArmy()->pos;

	//	Following code is never reached.

	//if (api.HamDistance(start, m_target) == 0)
	//{
	//	LOG << get_type() << " reach target" << endl;
	//	switch (api.GetMyArmy(m_name)->soldierType) {
	//	case (SOLDIER_INFANTRY):
	//		enter_state(m_name, this, new ManageState(m_name, m_target));
	//		return;
	//	case (SOLDIER_RANGER):
	//		enter_state(m_name, this, new ManageState(m_name, m_target));
	//		return;
	//	case (SOLDIER_CAVALRY):
	//		enter_state(m_name, this, new OffensiveBattleState(m_name));
	//		return;
	//	}
	//	return;
	//}

	//	try to move to target
	api.Move(BasicAI::instance()->get_action_queue(), start, m_target);
}

void OccupyingState::assign(GeneralType name, Position p)
{
	target_map[name] = p;
}

void OccupyingState::remove(GeneralType name)
{
	target_map.erase(name);
}

bool OccupyingState::city_assigned(Position p)
{
	for (std::map<GeneralType, Position>::iterator it = target_map.begin(); it != target_map.end(); ++it)
		if (it->second == p)
			return true;
	return false;
}

bool OccupyingState::find_target(GeneralType general, Position &target)
{
	//	TODO	remove dead generals from target_list

	UserAPI &api = BasicAI::instance()->get_api();
	int min_dist = INFINITY;
	target = Position(-1, -1);
	Position start = api.GetMyArmy(general)->pos;
	for (int i = 0; i < api.all_cities.size(); i ++)
		if (api.all_cities[i]->owner == -1) {
			Position t = api.GetCityCenter(api.all_cities[i]);
			if (city_assigned(t)) continue;
			if (api.HamDistance(start, t) < min_dist) {
				min_dist = api.HamDistance(start, t);
				target = t;
			}
		}

	return (min_dist < INFINITY);
}

std::map<GeneralType, Position> OccupyingState::target_map;